package com.develop.wechatpay.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.develop.wechatpay.domain.WechatPayModel;
import com.develop.wechatpay.domain.WechatPayWSModelRe;
import com.develop.wechatpay.mapper.base.WSMapper;
import com.develop.wechatpay.service.KingdeeK3CloudService;
import com.develop.wechatpay.service.WeChatPayOrderService;
import com.develop.wechatpay.util.HttpUtils;
import com.develop.wechatpay.util.JSONObjectUtil;
import com.develop.wechatpay.util.WeChatPayUtil;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders;
import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import com.wechat.pay.contrib.apache.httpclient.util.PaySignUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.XmlUtil;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class WeChatPayOrderServiceImpl implements WeChatPayOrderService {

    @Value("${wechat.pay.priKeyPath}")
    private String priKeyPath;//商户私钥地址

    @Value("${wechat.pay.merchantId}")
    private String merchantId; // 商户号

    @Value("${wechat.pay.appid}")
    private String appid;//公众号Id

    @Value("${wechat.pay.merchantSerialNumber}")
    private String merchantSerialNumber; // 商户证书序列号

    @Value("${wechat.pay.apiV3Key}")
    private String apiV3Key; // API V3密钥

    @Value("${wechat.pay.notify_url}")
    private String notify_url;//微信通知接口

    @Autowired
    private KingdeeK3CloudService kingdeeK3CloudService;
    @Autowired
    private WSMapper wsMapper;


    public WeChatPayOrderServiceImpl() {
    }


    @Override
    public JSONObject jsapiAddOrder(WechatPayModel wechatPayModel) throws Exception {
        log.info("jsapiAddOrder发起" + JSONObject.toJSONString(wechatPayModel));
        WeChatPayUtil.checkParam(wechatPayModel, priKeyPath, merchantId, appid, merchantSerialNumber, apiV3Key, notify_url);
        CloseableHttpClient closeableHttpClient = null;
        try {
            closeableHttpClient = WeChatPayUtil.GetWeChatPayHttpClient(priKeyPath, merchantId, merchantSerialNumber, apiV3Key);
            JSONObject jsonObject = WeChatPayUtil.jsapiAddOrder(closeableHttpClient, wechatPayModel);
            log.info("jsapiAddOrder返回" + jsonObject.toJSONString());
            if (jsonObject.containsKey("code") && jsonObject.containsKey("message")) {
                //异常
                String code = jsonObject.getString("code");
                String message = jsonObject.getString("message");
                String errorMsg = message + "[" + code + "]";
                return JSONObjectUtil.ReErrorJson(null, errorMsg);
            } else if (jsonObject.containsKey("prepay_id")) {
                //正常
                return JSONObjectUtil.ReSuccessJson(jsonObject);
            } else {
                //异常
                return JSONObjectUtil.ReErrorJson(jsonObject, "");
            }
        } catch (Exception ex) {
            return JSONObjectUtil.ReErrorJson(null, ex.getMessage());
        } finally {
            if (closeableHttpClient != null) {
                closeableHttpClient.close();
            }
        }
    }

    @Override
    public JSONObject getNativeNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            String wechatPaySerial = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SERIAL);
            String nonce = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_NONCE); // 请求头Wechatpay-Nonce
            String timestamp = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_TIMESTAMP); // 请求头Wechatpay-Timestamp
            String signature = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SIGNATURE); // 请求头Wechatpay-Signature
            log.info("返回解析前请求头：" + wechatPaySerial);
            log.info("返回解析前请求头：" + nonce);
            log.info("返回解析前请求头：" + timestamp);
            log.info("返回解析前请求头：" + signature);
            Verifier verifier = WeChatPayUtil.GetVerifier(priKeyPath, merchantId, merchantSerialNumber, apiV3Key);
            //处理通知参数
            String body = HttpUtils.readData(request);
            log.info("返回解析前：" + body);
            //回调通知的验签与解密
            // 构建request，传入必要参数
            NotificationRequest requestN = new NotificationRequest.Builder().withSerialNumber(wechatPaySerial)
                    .withNonce(nonce)
                    .withTimestamp(timestamp)
                    .withSignature(signature)
                    .withBody(body)
                    .build();
            NotificationHandler handler = new NotificationHandler(verifier, apiV3Key.getBytes(StandardCharsets.UTF_8));
            // 验签和解析请求体
            Notification notification = handler.parse(requestN);
            log.info("返回解析后：" + JSONObject.toJSONString(notification));
            String eventType = notification.getEventType();
            String resourceType = notification.getResourceType();
            String summary = notification.getSummary();
            String decryptData = notification.getDecryptData();
            if (StrUtil.isBlank(eventType) || StrUtil.isBlank(decryptData)) {
                log.error("消息通知异常eventType或decryptData为空!");
                response.setStatus(500);
                return JSONObjectUtil.ReWXPayJson("FAIL", "失败[" + summary + "][消息通知异常eventType或decryptData为空]");
            }
            JSONObject data = JSONObject.parseObject(decryptData);
            String trade_state = data.getString("trade_state");
            String trade_state_desc = data.getString("trade_state_desc");
            String out_trade_no = data.getString("out_trade_no");
            JSONObject payer = data.getJSONObject("payer");
            if (StrUtil.isBlank(trade_state) || StrUtil.isBlank(trade_state_desc) || StrUtil.isBlank(out_trade_no) || payer == null || !payer.containsKey("openid")) {
                log.error("消息通知异常trade_state,trade_state_desc,out_trade_no,payer为空!");
                response.setStatus(500);
                return JSONObjectUtil.ReWXPayJson("FAIL", "失败[" + summary + "][消息通知异常trade_state,trade_state_desc,out_trade_no,payer为空!]");
            }
            String openid = payer.getString("openid");
            if (StrUtil.isBlank(openid)) {
                log.error("消息通知异常openid为空!");
                response.setStatus(500);
                return JSONObjectUtil.ReWXPayJson("FAIL", "失败[" + summary + "][消息通知异常openid为空]");
            }
            //反写金蝶
            JSONObject jsonObjectKingdee = new JSONObject();
            jsonObjectKingdee.put("url", "/Sale/SaleOrderPayResultByWxTZ");
            jsonObjectKingdee.put("FWeUserId", openid);
            JSONObject jsonObjectKingdeeParam = new JSONObject();
            jsonObjectKingdeeParam.put("event_type", eventType);
            jsonObjectKingdeeParam.put("resource_type", resourceType);
            jsonObjectKingdeeParam.put("out_trade_no", out_trade_no);
            jsonObjectKingdeeParam.put("trade_state", trade_state);
            jsonObjectKingdeeParam.put("trade_state_desc", trade_state_desc);
            jsonObjectKingdeeParam.put("summary", summary);
            jsonObjectKingdee.put("FParam", jsonObjectKingdeeParam);
            JSONObject jsonObject = kingdeeK3CloudService.sendPostRequestAutoLogin("Develop.ThirdParty.Integration.ExcSQLWebApiWithout.SelectData,Develop.ThirdParty.Integration.common.kdsvc", jsonObjectKingdee);
            if (jsonObject == null) {
                log.error("反写金蝶状态异常返回值为空!");
                response.setStatus(500);
                return JSONObjectUtil.ReWXPayJson("FAIL", "失败[" + summary + "]");
            } else {
                log.error("反写金蝶状态Json串:" + jsonObject.toJSONString());
                int code = jsonObject.getIntValue("code");
                if (code != 200) {
                    log.error("反写金蝶状态异常:" + jsonObject.toJSONString());
                    response.setStatus(500);
                    return JSONObjectUtil.ReWXPayJson("FAIL", "失败[" + summary + "]");
                }
            }

            if (eventType.equals("TRANSACTION.SUCCESS")) {
                response.setStatus(200);
                return JSONObjectUtil.ReWXPayJson("SUCCESS", "成功");
            } else {
                log.error("支付异常异常" + summary + "!");
                response.setStatus(500);
                return JSONObjectUtil.ReWXPayJson("FAIL", "失败[" + summary + "]");
            }
        } catch (Exception e) {
            response.setStatus(500);
            log.error("通知异常：" + e.getMessage(), e);
            return JSONObjectUtil.ReWXPayJson("FAIL", e.getMessage());
        }
    }

    public String HandleWSNativeNotifyRe(String return_codeP, String return_msgP, WechatPayWSModelRe wechatPayWSModelRe) {
        try {
            Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            Element xml = doc.createElement("xml");
            Node return_codeV = doc.createCDATASection("return_code");
            return_codeV.setTextContent(return_codeP);

            Node return_msgV = doc.createCDATASection("return_msg");
            return_msgV.setTextContent(return_msgP);

            Element return_code = doc.createElement("return_code");
            Element return_msg = doc.createElement("return_msg");
            return_code.appendChild(return_codeV);
            return_msg.appendChild(return_msgV);

            xml.appendChild(return_code);
            xml.appendChild(return_msg);
            doc.appendChild(xml);
            String FReWSXml = XmlUtil.toStr(doc, false).replace("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>", "").replaceAll("\n", "");
            wechatPayWSModelRe.setFReWSXml(FReWSXml);
            return FReWSXml;
        } catch (Exception ex) {
            String FErrorMsg = "<xml><return_code><![CDATA[500]]></return_code><return_msg><![CDATA[" + ex.getMessage() + "]]></return_msg></xml>";
            wechatPayWSModelRe.setFReWSXml(FErrorMsg);
            return FErrorMsg;
        }

    }

    @Override
    public String getWSNativeNotify(HttpServletRequest request, HttpServletResponse response) {
        WechatPayWSModelRe wechatPayWSModelRe = new WechatPayWSModelRe();
        try {
            Enumeration<String> headerNames = request.getHeaderNames();
            if (headerNames != null) {
                while (headerNames.hasMoreElements()) {
                    String name = headerNames.nextElement();
                    log.info("旺盛请求头>" + name + ":" + request.getHeader(name) + "<br>");
                }
            }
            String body = HttpUtils.readData(request);
            wechatPayWSModelRe.setFWSTZXml(body);
            log.info("获取请求体>" + body);
            if (body != null && body.length() >= 1) {
                Map<String, Object> mapXml = XmlUtil.xmlToMap(body);
                if (mapXml != null && mapXml.size() >= 1) {
                    wechatPayWSModelRe = JSONUtil.toBean(JSONUtil.parseObj(mapXml), WechatPayWSModelRe.class);
                    String appid = wechatPayWSModelRe.getAppid();//微信公众号id
                    String bank_type = wechatPayWSModelRe.getBank_type();//银行类型，采用字符串类型的银行标识。银行标识请参考[《银行类型对照表》](/merchant-articles/development/chart/bank-type.md。
                    String cash_fee = wechatPayWSModelRe.getCash_fee();
                    String device_info = wechatPayWSModelRe.getDevice_info();
                    String fee_type = wechatPayWSModelRe.getFee_type();
                    String is_subscribe = wechatPayWSModelRe.getIs_subscribe();
                    String mch_id = wechatPayWSModelRe.getMch_id();//商户号
                    String nonce_str = wechatPayWSModelRe.getNonce_str();//随机字符
                    String openid = wechatPayWSModelRe.getOpenid();//微信用户ID
                    String out_trade_no = wechatPayWSModelRe.getOut_trade_no();//内部订单号
                    String result_code = wechatPayWSModelRe.getResult_code();
                    String return_code = wechatPayWSModelRe.getReturn_code();
                    String sign = wechatPayWSModelRe.getSign();//签名
                    String sub_appid = wechatPayWSModelRe.getSub_appid();
                    String sub_is_subscribe = wechatPayWSModelRe.getSub_is_subscribe();
                    String sub_mch_id = wechatPayWSModelRe.getSub_mch_id();
                    String sub_openid = wechatPayWSModelRe.getSub_openid();
                    String time_end = wechatPayWSModelRe.getTime_end();//订单结束时间
                    String total_fee = wechatPayWSModelRe.getTotal_fee();
                    String trade_type = wechatPayWSModelRe.getTrade_type();//交易类型，枚举值：JSAPI：公众号支付  NATIVE：扫码支付  App：App支付   MICROPAY：付款码支付 MWEB：H5支付 FACEPAY：刷脸支付
                    String transaction_id = wechatPayWSModelRe.getTransaction_id();//微信支付系统生成的订单号

                    if (StrUtil.isBlank(return_code) || StrUtil.isBlank(result_code)) {
                        log.error("消息通知异常result_code或result_code为空!");
                        wechatPayWSModelRe.setFErrorMsg("消息通知异常result_code或result_code为空!");
                        return HandleWSNativeNotifyRe("Error", "Error", wechatPayWSModelRe);
                    }

                    if (StrUtil.isBlank(appid) || StrUtil.isBlank(openid) || StrUtil.isBlank(sub_openid) || StrUtil.isBlank(out_trade_no) || StrUtil.isBlank(mch_id)) {
                        log.error("消息通知异常appid,openid,sub_openid,out_trade_no,mch_id为空!");
                        wechatPayWSModelRe.setFErrorMsg("消息通知异常appid,openid,sub_openid,out_trade_no,mch_id为空!");
                        return HandleWSNativeNotifyRe("Error", "Error", wechatPayWSModelRe);
                    }
                    String[] out_trade_noArr = out_trade_no.split("_");
                    if (out_trade_noArr.length != 4) {
                        log.error("out_trade_no不是金蝶订单无需消息通知!");
                        wechatPayWSModelRe.setFErrorMsg("out_trade_no不是金蝶订单无需消息通知!");
                        return HandleWSNativeNotifyRe("Error", "Error", wechatPayWSModelRe);
                    }
                    String out_trade_noNew = out_trade_noArr[0] + "_" + out_trade_noArr[1];
                    if (!out_trade_noNew.endsWith("_JD")) {
                        log.error("out_trade_no不是金蝶订单无需消息通知!");
                        wechatPayWSModelRe.setFErrorMsg("out_trade_no不是金蝶订单无需消息通知!");
                        return HandleWSNativeNotifyRe("Error", "Error", wechatPayWSModelRe);
                    }
                    return SaleOrderPayResultByWxTZ(sub_openid, out_trade_noNew, result_code, wechatPayWSModelRe);
                } else {
                    log.error("旺盛请求体为空");
                    wechatPayWSModelRe.setFErrorMsg("旺盛请求体为空");
                    return HandleWSNativeNotifyRe("Error", "Error", wechatPayWSModelRe);
                }

            } else {
                log.error("旺盛请求体为空");
                wechatPayWSModelRe.setFErrorMsg("旺盛请求体为空");
                return HandleWSNativeNotifyRe("Error", "Error", wechatPayWSModelRe);
            }

        } catch (Exception ex) {
            log.error("系统异常:" + ex.getMessage());
            wechatPayWSModelRe.setFErrorMsg("系统异常:" + ex.getMessage());
            return HandleWSNativeNotifyRe("Error", "Error", wechatPayWSModelRe);
        } finally {
            //记录日志
            try {
                wsMapper.insertWSWeChatPayReLog(wechatPayWSModelRe);
            } catch (Exception ex) {
                log.error("系统异常:" + ex.getMessage());
            }
        }
    }

    public String SaleOrderPayResultByWxTZ(String sub_openid, String out_trade_noNew, String result_code, WechatPayWSModelRe wechatPayWSModelRe) throws Exception {
        //反写金蝶
        JSONObject jsonObjectKingdee = new JSONObject();
        jsonObjectKingdee.put("url", "/Sale/SaleOrderPayResultByWxTZ");
        jsonObjectKingdee.put("FWeUserId", sub_openid);
        JSONObject jsonObjectKingdeeParam = new JSONObject();
        jsonObjectKingdeeParam.put("out_trade_no", out_trade_noNew);
        jsonObjectKingdeeParam.put("event_type", result_code);
        jsonObjectKingdeeParam.put("resource_type", result_code);
        jsonObjectKingdeeParam.put("trade_state", result_code);
        jsonObjectKingdeeParam.put("trade_state_desc", result_code);
        jsonObjectKingdeeParam.put("summary", result_code);
        jsonObjectKingdee.put("FParam", jsonObjectKingdeeParam);

        JSONObject jsonObject = kingdeeK3CloudService.sendPostRequestAutoLogin("Develop.ThirdParty.Integration.ExcSQLWebApiWithout.SelectData,Develop.ThirdParty.Integration.common.kdsvc", jsonObjectKingdee);
        if (jsonObject == null) {
            log.error("第一次反写金蝶状态异常返回值为空!");
            wechatPayWSModelRe.setFErrorMsg("第一次反写金蝶状态异常返回值为空!");
            return HandleWSNativeNotifyRe("Error", "Error", wechatPayWSModelRe);
        } else {
            log.error("第一次反写金蝶状态Json串:" + jsonObject.toJSONString());
            int code = jsonObject.getIntValue("code");
            if (code != 200) {
                if (jsonObject.toJSONString().indexOf("已返回支付结果") > -1) {
                    return HandleWSNativeNotifyRe("SUCCESS", "OK", wechatPayWSModelRe);
                }
                return SaleOrderPayResultByWxTZNoError(sub_openid, out_trade_noNew, result_code, wechatPayWSModelRe);
            } else {
                return HandleWSNativeNotifyRe("SUCCESS", "OK", wechatPayWSModelRe);
            }
        }
    }

    public String SaleOrderPayResultByWxTZNoError(String sub_openid, String out_trade_noNew, String result_code, WechatPayWSModelRe wechatPayWSModelRe) throws Exception {
        //反写金蝶
        JSONObject jsonObjectKingdee = new JSONObject();
        jsonObjectKingdee.put("url", "/Sale/SaleOrderPayResultByWxTZNoError");
        jsonObjectKingdee.put("FWeUserId", sub_openid);
        JSONObject jsonObjectKingdeeParam = new JSONObject();
        jsonObjectKingdeeParam.put("out_trade_no", out_trade_noNew);
        jsonObjectKingdeeParam.put("event_type", result_code);
        jsonObjectKingdeeParam.put("resource_type", result_code);
        jsonObjectKingdeeParam.put("trade_state", result_code);
        jsonObjectKingdeeParam.put("trade_state_desc", result_code);
        jsonObjectKingdeeParam.put("summary", result_code);
        jsonObjectKingdee.put("FParam", jsonObjectKingdeeParam);

        JSONObject jsonObject = kingdeeK3CloudService.sendPostRequestAutoLogin("Develop.ThirdParty.Integration.ExcSQLWebApiWithout.SelectData,Develop.ThirdParty.Integration.common.kdsvc", jsonObjectKingdee);
        if (jsonObject == null) {
            log.error("第二次反写金蝶状态异常返回值为空!");
            wechatPayWSModelRe.setFErrorMsg("反写金蝶状态异常返回值为空!");
            return HandleWSNativeNotifyRe("Error", "Error", wechatPayWSModelRe);
        } else {
            log.error("第二次反写金蝶状态Json串:" + jsonObject.toJSONString());
            int code = jsonObject.getIntValue("code");
            if (code != 200) {
                if (jsonObject.toJSONString().indexOf("已返回支付结果") > -1) {
                    return HandleWSNativeNotifyRe("SUCCESS", "OK", wechatPayWSModelRe);
                }
                log.error("第二次反写金蝶状态异常:" + jsonObject.toJSONString());
                wechatPayWSModelRe.setFErrorMsg("第二次反写金蝶状态异常:" + jsonObject.toJSONString());
                return HandleWSNativeNotifyRe("Error", "Error", wechatPayWSModelRe);
            } else {
                return HandleWSNativeNotifyRe("SUCCESS", "OK", wechatPayWSModelRe);
            }
        }
    }

    @Override
    public JSONObject queryOrderByOutRradeNo(String outRradeNo) throws Exception {
        CloseableHttpClient closeableHttpClient = null;
        try {
            closeableHttpClient = WeChatPayUtil.GetWeChatPayHttpClient(priKeyPath, merchantId, merchantSerialNumber, apiV3Key);
            return WeChatPayUtil.queryOrderByOutRradeNo(closeableHttpClient, outRradeNo, merchantId);
        } catch (Exception ex) {
            return JSONObjectUtil.ReErrorJson(null, ex.getMessage());
        } finally {
            if (closeableHttpClient != null) {
                closeableHttpClient.close();
            }
        }
    }

    @Override
    public JSONObject queryOrderByTransactionId(String transactionId) throws IOException {
        CloseableHttpClient closeableHttpClient = null;
        try {
            closeableHttpClient = WeChatPayUtil.GetWeChatPayHttpClient(priKeyPath, merchantId, merchantSerialNumber, apiV3Key);
            return WeChatPayUtil.queryOrderByTransactionId(closeableHttpClient, transactionId, merchantId);
        } catch (Exception ex) {
            return JSONObjectUtil.ReErrorJson(null, ex.getMessage());
        } finally {
            if (closeableHttpClient != null) {
                closeableHttpClient.close();
            }
        }
    }

    @Override
    public JSONObject closeOrderByOutRradeNo(String outRradeNo) throws IOException {
        CloseableHttpClient closeableHttpClient = null;
        try {
            closeableHttpClient = WeChatPayUtil.GetWeChatPayHttpClient(priKeyPath, merchantId, merchantSerialNumber, apiV3Key);
            return WeChatPayUtil.closeOrderByOutRradeNo(closeableHttpClient, outRradeNo, merchantId);
        } catch (Exception ex) {
            return JSONObjectUtil.ReErrorJson(null, ex.getMessage());
        } finally {
            if (closeableHttpClient != null) {
                closeableHttpClient.close();
            }
        }
    }

    @Override
    public String getPaySign(String timestamp, String nonceStr, String prepay_id) throws NoSuchAlgorithmException, FileNotFoundException, SignatureException, InvalidKeyException, UnsupportedEncodingException {
        return PaySignUtil.getPaySign(priKeyPath, appid, timestamp, nonceStr, prepay_id);
    }

    @Override
    public JSONObject getTradeBillFile(String bill_date, String bill_type, String tar_type) throws IOException {
        CloseableHttpClient closeableHttpClient = null;
        try {
            closeableHttpClient = WeChatPayUtil.GetWeChatPayHttpClient(priKeyPath, merchantId, merchantSerialNumber, apiV3Key);
            return WeChatPayUtil.getTradeBillFile(closeableHttpClient, bill_date, bill_type, tar_type);
        } catch (Exception ex) {
            return JSONObjectUtil.ReErrorJson(null, ex.getMessage());
        } finally {
            if (closeableHttpClient != null) {
                closeableHttpClient.close();
            }
        }
    }

    @Override
    public JSONObject getFundFlowBillFile(String bill_date, String account_type, String tar_type) throws IOException {
        CloseableHttpClient closeableHttpClient = null;
        try {
            closeableHttpClient = WeChatPayUtil.GetWeChatPayHttpClient(priKeyPath, merchantId, merchantSerialNumber, apiV3Key);
            return WeChatPayUtil.getFundFlowBillFile(closeableHttpClient, bill_date, account_type, tar_type);
        } catch (Exception ex) {
            return JSONObjectUtil.ReErrorJson(null, ex.getMessage());
        } finally {
            if (closeableHttpClient != null) {
                closeableHttpClient.close();
            }
        }
    }

}